load("@rules_java//java:defs.bzl", "java_binary", "java_library", "java_test")
load("//bazel:yr.bzl", "cc_strip")
load("//bazel:yr_java.bzl", "group_of_java_tests")

package(default_visibility = ["//visibility:public"])

java_plugin(
    name = "lombok_edge_basic_plugin",
    processor_class = "lombok.launch.AnnotationProcessorHider$AnnotationProcessor",
    visibility = ["//visibility:public"],
    deps = ["@maven//:org_projectlombok_lombok"],
)

java_library(
    name = "lombok_basic_edge",
    exported_plugins = [":lombok_edge_basic_plugin"],
    visibility = ["//visibility:public"],
    exports = ["@maven//:org_projectlombok_lombok"],
)

java_library(
    name = "function_common",
    srcs = glob([
        "function-common/src/main/java/**/*.java",
    ]),
    deps = [
        "//api/java:lombok_basic_edge",
        "//src/proto:libruntime_java_proto",
        "//src/proto:socket_java_proto",
        "@maven//:com_google_code_gson_gson",
        "@maven//:org_projectlombok_lombok",
        "@maven//:com_fasterxml_jackson_core_jackson_core",
        "@maven//:com_fasterxml_jackson_core_jackson_annotations",
        "@maven//:commons_io_commons_io_2_16_1",
        "@maven//:org_msgpack_jackson_dataformat_msgpack",
        "@maven//:org_msgpack_msgpack_core",
        "@maven//:org_slf4j_slf4j_api",
        "@maven//:com_fasterxml_jackson_core_jackson_databind",
        "@maven//:org_apache_logging_log4j_log4j_slf4j_impl",
        "@maven//:org_apache_logging_log4j_log4j_api",
        "@maven//:org_apache_logging_log4j_log4j_core",
        "@maven//:org_apache_commons_commons_lang3",
        "@maven//:org_ow2_asm_asm",
    ],
)

java_library(
    name = "lib_yr_api_sdk",
    srcs = glob([
        "yr-api-sdk/src/main/java/**/*.java",
        "function-common/src/main/java/**/*.java",
    ]),
    deps = [
        "//api/java:lombok_basic_edge",
        "//src/proto:libruntime_java_proto",
        "//src/proto:socket_java_proto",
        "@maven//:org_projectlombok_lombok",
        "@maven//:com_google_code_gson_gson",
        "@maven//:commons_io_commons_io_2_16_1",
        "@maven//:org_slf4j_slf4j_api",
        "@maven//:org_apache_logging_log4j_log4j_slf4j_impl",
        "@maven//:org_apache_logging_log4j_log4j_api",
        "@maven//:org_apache_logging_log4j_log4j_core",
        "@maven//:com_fasterxml_jackson_core_jackson_core",
        "@maven//:com_fasterxml_jackson_core_jackson_databind",
        "@maven//:com_fasterxml_jackson_core_jackson_annotations",
        "@maven//:org_msgpack_jackson_dataformat_msgpack",
        "@maven//:org_apache_commons_commons_lang3",
        "@maven//:org_ow2_asm_asm",
    ],
)

java_binary(
    name = "yr_runtime",
    srcs = glob([
        "yr-runtime/src/main/java/**/*.java",
    ]),
    deps = [
        "//api/java:lombok_basic_edge",
        "//api/java:function_common",
        "//src/proto:libruntime_java_proto",
        "@maven//:com_google_code_gson_gson",
        "@maven//:commons_io_commons_io_2_16_1",
        "@maven//:org_projectlombok_lombok",
        "@maven//:org_apache_logging_log4j_log4j_slf4j_impl",
        "@maven//:org_apache_logging_log4j_log4j_api",
        "@maven//:org_apache_logging_log4j_log4j_core",
        "@maven//:org_slf4j_slf4j_api",
        "@maven//:org_msgpack_jackson_dataformat_msgpack",
        "@maven//:com_fasterxml_jackson_core_jackson_core",
        "@maven//:com_fasterxml_jackson_core_jackson_databind",
        "@maven//:com_fasterxml_jackson_core_jackson_annotations",
        "@maven//:org_apache_commons_commons_lang3",
    ],
)

group_of_java_tests(
    test_suite_name = "all_yr_api_sdk_tests",
    test_classes = [
        "com.yuanrong.call.TestCppFunctionHandler",
        "com.yuanrong.call.TestCppInstanceCreator",
        "com.yuanrong.call.TestCppInstanceFunctionHandler",
        "com.yuanrong.call.TestCppInstanceHandler",
        "com.yuanrong.call.TestFunctionHandler",
        "com.yuanrong.call.TestInstanceFunctionHandler",
        "com.yuanrong.call.TestInstanceHandler",
        "com.yuanrong.call.TestJavaFunctionHandler",
        "com.yuanrong.call.TestJavaInstanceCreator",
        "com.yuanrong.call.TestJavaInstanceFunctionHandler",
        "com.yuanrong.call.TestJavaInstanceHandler",
        "com.yuanrong.runtime.TestClusterModeRuntime",
        "com.yuanrong.runtime.TestYR",
        "com.yuanrong.runtime.client.TestKVManager",
        "com.yuanrong.storage.TestWaitResult",
        "com.yuanrong.utils.TestSdkUtils",
        "com.yuanrong.TestConfig",
        "com.yuanrong.TestConfigManager",
        "com.yuanrong.TestGroup",
        "com.yuanrong.TestYRGetInstance"
    ], 
    srcs = glob([
        "yr-api-sdk/src/test/java/**/*.java",
    ]),
    deps = [
        ":create_native_jar",
        ":native_yr_api_sdk",
        ":lib_yr_api_sdk",
        "@maven//:junit_junit",
        "@maven//:org_mockito_mockito_core",
        "@maven//:org_powermock_powermock_core",
        "@maven//:org_powermock_powermock_module_junit4",
        "@maven//:org_powermock_powermock_api_mockito2",
        "@jacoco//:jacoco_agent",
    ],
    jvm_flags = [
        "-javaagent:$(execpath @jacoco//:jacoco_agent)=destfile=jacoco.exec",
    ],
    local = True,
)

group_of_java_tests(
    test_suite_name = "all_function_common_tests",
    test_classes = [
        "com.services.TestUDFManager",
        "com.services.logger.TestUserFunctionLogger",
        "com.services.model.TestCallRequest",
        "com.services.runtime.action.TestContextImpl",
        "com.services.runtime.action.TestCustomLoggerStream",
        "com.services.runtime.action.TestFunctionLoggerImpl",
        "com.services.runtime.utils.TestDataTypeAdapter",
        "com.services.runtime.utils.TestUtil",
        "com.yuanrong.TestGroupOptions",
        "com.yuanrong.TestInvokeOptions",
        "com.yuanrong.TestSetParam",
        "com.yuanrong.affinity.TestAffinity",
        "com.yuanrong.affinity.TestCondition",
        "com.yuanrong.affinity.TestInstanceAffinity",
        "com.yuanrong.affinity.TestLabelExpression",
        "com.yuanrong.affinity.TestLabelOperator",
        "com.yuanrong.affinity.TestResourceAffinity",
        "com.yuanrong.affinity.TestSubCondition",
        "com.yuanrong.api.TestInvokeArg",
        "com.yuanrong.errorcode.TestErrorCode",
        "com.yuanrong.errorcode.TestErrorInfo",
        "com.yuanrong.errorcode.TestPair",
        "com.yuanrong.exception.TestYRException",
        "com.yuanrong.exception.TestFunctionRuntimeException",
        "com.yuanrong.exception.TestHandlerNotAvailableException",
        "com.yuanrong.exception.TestJNIException",
        "com.yuanrong.exception.TestLibRuntimeException",
        "com.yuanrong.exception.TestPosixCallException",
        "com.yuanrong.exception.TestStatusCode",
        "com.yuanrong.exception.handle.filter.TestFilterFactory",
        "com.yuanrong.exception.handle.filter.TestFuncCallStackTraceFilter",
        "com.yuanrong.exception.handle.filter.TestUserStackTraceFilter",
        "com.yuanrong.exception.handle.traceback.TestStackTraceInfo",
        "com.yuanrong.exception.handle.traceback.TestStackTraceUtils",
        "com.yuanrong.instance.TestDataObject",
        "com.yuanrong.instance.TestFunctionMetaFactory",
        "com.yuanrong.jni.TestLibRunTimeConfig",
        "com.yuanrong.jni.TestLoadUtil",
        "com.yuanrong.runtime.TestObjectRef",
        "com.yuanrong.runtime.TestReferenceCount",
        "com.yuanrong.runtime.TestRuntimeContext",
        "com.yuanrong.runtime.TestUtils",
        "com.yuanrong.serialization.TestStrategy",
        "com.yuanrong.storage.TestInternalWaitResult",
    ],
    srcs = glob([
        "function-common/src/test/java/**/*.java",
    ]),
    deps = [
        "//api/java:function_common",
        "//src/proto:libruntime_java_proto",
        "@maven//:junit_junit",
        "@maven//:com_google_code_gson_gson",
        "@maven//:org_mockito_mockito_core",
        "@maven//:org_powermock_powermock_core",
        "@maven//:org_powermock_powermock_module_junit4",
        "@maven//:org_powermock_powermock_api_mockito2",
        "@jacoco//:jacoco_agent",
    ],
    jvm_flags = [
        "-javaagent:$(execpath @jacoco//:jacoco_agent)=destfile=jacoco.exec",
    ],
    local = True
)

group_of_java_tests(
    test_suite_name = "all_yr_runtime_tests",
    test_classes = [
        "com.yuanrong.codemanager.TestCodeExecutor",
        "com.yuanrong.codemanager.TestCodeLoader",
        "com.yuanrong.executor.TestFunctionHandler",
        "com.yuanrong.executor.TestReturnType",
        "com.yuanrong.runtime.server.TestRuntimeLogger",
        "com.yuanrong.TestEntrypoint"
    ],
    srcs = glob([
        "yr-runtime/src/test/java/**/*.java",
    ]),
    deps = [
        "//api/java:function_common",
        "//src/proto:libruntime_java_proto",
        "//api/java:yr_runtime",
        "@maven//:com_google_code_gson_gson",
        "@maven//:junit_junit",
        "@maven//:org_mockito_mockito_core",
        "@maven//:org_powermock_powermock_api_mockito2",
        "@maven//:org_powermock_powermock_core",
        "@maven//:org_powermock_powermock_module_junit4",
        "@maven//:org_powermock_powermock_reflect",
        "@maven//:org_powermock_powermock_api_support",
        "@maven//:org_apache_logging_log4j_log4j_api",
        "@maven//:org_projectlombok_lombok",
        "@jacoco//:jacoco_agent",
    ],
    jvm_flags = [
        "-javaagent:$(execpath @jacoco//:jacoco_agent)=destfile=jacoco.exec",
    ],
    local = True
)

cc_strip(
    name = "java_strip",
    srcs = ["//api/java/function-common/src/main/cpp:libruntime_lib_jni.so"],
)

genrule(
    name = "create_native_jar",
    srcs = [
        "//api/java:lib_yr_api_sdk",
        "//src/proto:libruntime_java_proto",
        "//src/proto:socket_java_proto",
        "//api/java/function-common/src/main/cpp:libruntime_lib_jni.so",
        "//:grpc_strip",
        "@datasystem_sdk//:shared",
        "@metrics_sdk//:shared",
    ],
    outs = ["native_yr_api_sdk.jar"],
    cmd = """
    # make folders
    BASE_DIR=$$(pwd)
    WORKING_DIR=$$BASE_DIR/temp
    NATIVE_DIR=$$WORKING_DIR/native/$$(uname -m)
    JAVA_SDK_DIR=$$BASE_DIR/build/output/runtime/sdk/java
    rm -rf $$WORKING_DIR $$JAVA_SDK_DIR
    mkdir -p $$NATIVE_DIR $$JAVA_SDK_DIR
    chmod +w $(locations //api/java/function-common/src/main/cpp:libruntime_lib_jni.so) && chrpath -r '$$ORIGIN' $(locations //api/java/function-common/src/main/cpp:libruntime_lib_jni.so) &&
    chmod +w $(locations //:grpc_strip) && chrpath -d $(locations //:grpc_strip)
    # decompress jars to WORKING_DIR
    cd $$WORKING_DIR
    jar xf $$BASE_DIR/$(locations //api/java:lib_yr_api_sdk)
    LIBRUNTIME_PROTO_JAR=$$(echo $(locations //src/proto:libruntime_java_proto) | awk '{print $$1}')
    jar xf $$BASE_DIR/$$LIBRUNTIME_PROTO_JAR
    SOCKET_PROTO_JAR=$$(echo $(locations //src/proto:socket_java_proto) | awk '{print $$1}')
    jar xf $$BASE_DIR/$$SOCKET_PROTO_JAR

    # copy native lib to WORKING_DIR
    cd $$BASE_DIR
    NATIVE_LIB=$$(echo $(locations @datasystem_sdk//:shared))
    NATIVE_LIB=$$(echo $$NATIVE_LIB $(locations @metrics_sdk//:shared))
    NATIVE_LIB=$$(echo $$NATIVE_LIB $(locations //:grpc_strip))
    NATIVE_LIB=$$(echo $$NATIVE_LIB $(locations //api/java/function-common/src/main/cpp:libruntime_lib_jni.so))
    LIB_REQUIRED=(
        "libtbb.so.2"
        "libds-spdlog.so.1.12.0"
        "libzmq.so.5.2.5"
        "libsecurec.so"
        "libssl.so.1.1"
        "libcrypto.so.1.1"
        "libaddress_sorting.so.42.0.0"
        "libdatasystem.so"
        "libgrpc_dynamic.so.1.65.4"
        "libspdlog.so.1.12.0"
        "libyrlogs.so"
        "liblitebus.so.0.0.1"
        "libobservability-metrics-sdk.so"
        "libobservability-metrics.so"
        "libruntime_lib_jni.so")

    unique_array=()

    for f in $$NATIVE_LIB;
    do
        filename=$$(basename $$f)
        if [[ ! "$${unique_array[*]-}" =~ "$${filename}" ]]; then
            unique_array+=("$$filename")
        else
            echo "$$f already existed."
            continue
        fi
        if [[ -L $$f || ! "$${LIB_REQUIRED[@]}" =~ "$$filename" ]];then
            continue
        fi
        cp -a $$f $$NATIVE_DIR
        echo $$f $$filename
        sha256value=$$(sha256sum $$f | awk '{{print $$1}}')
        echo "$$filename=$$sha256value" >> $$NATIVE_DIR/so.properties
    done

    # make jar with native files
    cd $$WORKING_DIR
    zip -rqy yr_api_sdk.jar .
    cp -rf yr_api_sdk.jar $$JAVA_SDK_DIR/yr-api-sdk-$$BUILD_VERSION.jar
    cp $$BASE_DIR/api/java/yr-api-sdk/resource/sdkpom.xml $$JAVA_SDK_DIR/pom.xml

    cd $$BASE_DIR && cp -rf $$WORKING_DIR/yr_api_sdk.jar $@
    """,
    local = True,
)

java_library(
    name = "native_yr_api_sdk",
    srcs = [],
    deps = [],
    runtime_deps = [":native_yr_api_sdk.jar"],
    data = ["native_yr_api_sdk.jar"]
)

genrule(
    name = "yr_java_pkg",
    srcs = [
        ":java_strip",
        "//:grpc_strip",
        "yr_runtime_deploy.jar",
        ":create_native_jar",
    ],
    outs = ["yr_java_pkg.out"],
    cmd = """
        BASE_DIR="$$(pwd)" &&
        JAVA_SDK_DIR=$$BASE_DIR/build/output/runtime/sdk/java &&
        JAVA_SERVICE_DIR=$$BASE_DIR/build/output/runtime/service/java &&
        rm -rf $$JAVA_SERVICE_DIR  && mkdir -p $$JAVA_SERVICE_DIR &&
        echo "$(locations :create_native_jar)"
        cp -rf $(locations yr_runtime_deploy.jar) $$JAVA_SERVICE_DIR/yr-runtime-1.0.0.jar &&
        cp -rf $$BASE_DIR/api/java/yr-runtime/src/main/resources/* $$JAVA_SERVICE_DIR/ &&
        mkdir -p $$JAVA_SERVICE_DIR/lib &&
        chmod +w $(locations :java_strip) $(locations //:grpc_strip) &&
        chrpath -r '$$ORIGIN' $(locations :java_strip) &&
        chrpath -d $(locations //:grpc_strip)
        cp -fr $(locations :java_strip) $(locations //:grpc_strip) $$JAVA_SERVICE_DIR/lib &&
        DATASYSTEM_DIR=$$BASE_DIR/external/datasystem_sdk &&
        METRICS_DIR=$$BASE_DIR/external/metrics_sdk &&
        cp -rf $$DATASYSTEM_DIR/cpp/lib/* $$JAVA_SERVICE_DIR/lib &&
        cp -rf $$METRICS_DIR/lib/* $$JAVA_SERVICE_DIR/lib &&
        echo "$$BASE_DIR" > $@
    """,
    local = True,
    visibility = ["//visibility:public"],
)

test_suite(
    name = "java_tests",
    tests = [
      "//api/java:all_yr_api_sdk_tests",
      "//api/java:all_function_common_tests",
      "//api/java:all_yr_runtime_tests"
    ]
)
